﻿Imports System.Net.Sockets
Imports System.Net
Imports MapleLib.MapleCryptoLib
Imports MMSServerPayBack.Functions
Imports System.IO
Imports System.Data.SqlClient

Public Class Main
    Private LoginServer As Socket
    Public backlog As Integer

    Private AuthServer As Socket
    Public AuthLog As Integer
    Public Clients As New List(Of MapleClient)

    Private Sub Main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        WriteLine("Server Starting", 3)

        AuthServer = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        AuthServer.Bind(New IPEndPoint(IPAddress.Parse(Settings.IP), 47611))
        AuthServer.Listen(AuthLog)
        BeginAuthListenerAccept(Nothing)

        LoginServer = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        LoginServer.Bind(New IPEndPoint(IPAddress.Parse(Settings.IP), Settings.Port))
        LoginServer.Listen(backlog)
        BeginLoginListenerAccept(Nothing)

        WriteLine("Server Started and Listening", 3)
    End Sub

    Public Delegate Sub WriteLineDelegate(ByVal text As String, ByVal type As Short)
    Public Sub WriteLine(ByVal text As String, Optional ByVal type As Short = 0)
        If InvokeRequired Then
            Dim delegate1 As New Main.WriteLineDelegate(AddressOf WriteLine)
            Dim parameters(1) As Object
            parameters(0) = text
            parameters(1) = type
            Invoke(delegate1, parameters)
        Else
            Dim now As String = Date.Now.ToLongTimeString
            Select Case type
                Case 1
                    text = String.Format("[Error] {0}", text)
                Case 2
                    text = String.Format("[Warning] {0}", text)
                Case 3
                    text = String.Format("[Info] {0}", text)
                Case Else
                    text = text
            End Select
            TextBox1.Text += String.Format("{0}:{1}{2}", now, text, Environment.NewLine)
        End If
    End Sub
#Region "Server"
    Private Sub BeginLoginListenerAccept(ByVal pArgs As SocketAsyncEventArgs)
        If pArgs Is Nothing Then
            pArgs = New SocketAsyncEventArgs()
            AddHandler pArgs.Completed, AddressOf EndLoginListenerAccept
        End If
        pArgs.AcceptSocket = Nothing
        If Not LoginServer.AcceptAsync(pArgs) Then
            EndLoginListenerAccept(Nothing, pArgs)
        End If
    End Sub

    Private Sub EndLoginListenerAccept(ByVal sender As Object, ByVal pArguments As SocketAsyncEventArgs)
        Try
            If pArguments.SocketError = SocketError.Success Then
                Dim receiveIV As Byte() = New Byte(3) {}
                receiveIV(0) = RandomByte()
                receiveIV(1) = RandomByte()
                receiveIV(2) = RandomByte()
                receiveIV(3) = RandomByte()
                Dim sendIV As Byte() = New Byte(3) {}
                sendIV(0) = RandomByte()
                sendIV(1) = RandomByte()
                sendIV(2) = RandomByte()
                sendIV(3) = RandomByte()
                Dim _RIV As New MapleCrypto(receiveIV, Settings.mapleVersion)
                Dim _SIV As New MapleCrypto(sendIV, Settings.mapleVersion)
                Dim client As New MapleClient(pArguments.AcceptSocket, _RIV, _SIV, Me)
                client.SendHandshake(Settings.mapleVersion, Settings.PatchVersion, receiveIV, sendIV)
                Clients.Add(client)
                BeginLoginListenerAccept(pArguments)
            ElseIf pArguments.SocketError <> SocketError.OperationAborted Then
                WriteLine(String.Format("[Error] LoginListener Error: {0}", pArguments.SocketError))
            End If
        Catch generatedExceptionName As ObjectDisposedException
        Catch exc As Exception
            WriteLine(String.Format("[Error] LoginListener Exception: {0}", exc))
        End Try
    End Sub
#End Region
#Region "Auth"
    Private Sub BeginAuthListenerAccept(ByVal pArgs As SocketAsyncEventArgs)
        If pArgs Is Nothing Then
            pArgs = New SocketAsyncEventArgs()
            AddHandler pArgs.Completed, AddressOf EndAuthListenerAccept
        End If
        pArgs.AcceptSocket = Nothing
        If Not AuthServer.AcceptAsync(pArgs) Then
            EndAuthListenerAccept(Nothing, pArgs)
        End If
    End Sub

    Private Sub EndAuthListenerAccept(ByVal sender As Object, ByVal pArguments As SocketAsyncEventArgs)
        Try
            If pArguments.SocketError = SocketError.Success Then
                Dim ac As New AuthClient(pArguments.AcceptSocket)
                BeginAuthListenerAccept(pArguments)
            ElseIf pArguments.SocketError <> SocketError.OperationAborted Then
                WriteLine(String.Format("[Error] AuthListener Error: {0}", pArguments.SocketError))
            End If
        Catch generatedExceptionName As ObjectDisposedException
        Catch exc As Exception
            WriteLine(String.Format("[Error] AuthListener Exception: {0}", exc))
        End Try
    End Sub
#End Region
End Class
